package com.example.repository;

import com.example.model.Cart;
import com.example.model.CartItem;
import com.example.model.Product;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.util.Bytes;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.NavigableMap;
import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Repository
public class CartRepository {

    private final Connection hbaseConnection;
    private final ProductRepository productRepository;
    private static final TableName TABLE_NAME = TableName.valueOf("carts");
    private static final byte[] CF_ITEMS = Bytes.toBytes("items");
    private static final Logger logger = LoggerFactory.getLogger(CartRepository.class);

    @Autowired
    public CartRepository(Connection hbaseConnection, ProductRepository productRepository) {
        this.hbaseConnection = hbaseConnection;
        this.productRepository = productRepository;
    }

    public List<CartItem> getCartItems(String userId) throws IOException {
        List<CartItem> items = new ArrayList<>();
        try (Table table = hbaseConnection.getTable(TABLE_NAME)) {
            Get get = new Get(Bytes.toBytes(userId));
            get.addFamily(CF_ITEMS);
            Result result = table.get(get);
            if (result.isEmpty()) {
                return items;
            }

            NavigableMap<byte[], byte[]> familyMap = result.getFamilyMap(CF_ITEMS);
            if (familyMap != null) {
                for (NavigableMap.Entry<byte[], byte[]> entry : familyMap.entrySet()) {
                    String productId = Bytes.toString(entry.getKey());
                    int quantity = Bytes.toInt(entry.getValue());

                    // Denormalize product data for the cart item
                    Optional<Product> productOpt = productRepository.findById(productId);
                    if (productOpt.isPresent()) {
                        CartItem item = new CartItem();
                        item.setProduct(productOpt.get());
                        item.setQuantity(quantity);
                        items.add(item);
                    } else {
                        logger.warn("Product with ID {} found in cart for user {} but not in products table. Skipping item.", productId, userId);
                    }
                }
            }
        }
        return items;
    }

    public List<Cart> findAllCarts() throws IOException {
        List<Cart> carts = new ArrayList<>();
        try (Table table = hbaseConnection.getTable(TABLE_NAME)) {
            Scan scan = new Scan();
            scan.addFamily(CF_ITEMS);
            try (ResultScanner scanner = table.getScanner(scan)) {
                for (Result result : scanner) {
                    String userId = Bytes.toString(result.getRow());
                    List<CartItem> items = getCartItems(userId);
                    if (!items.isEmpty()) {
                        Cart cart = new Cart();
                        cart.setUserId(userId);
                        cart.setItems(items);
                        carts.add(cart);
                    }
                }
            }
        }
        return carts;
    }

    public void addItem(String userId, String productId, int quantity) throws IOException {
        try (Table table = hbaseConnection.getTable(TABLE_NAME)) {
            Put put = new Put(Bytes.toBytes(userId));
            put.addColumn(CF_ITEMS, Bytes.toBytes(productId), Bytes.toBytes(quantity));
            table.put(put);
        }
    }
    
    public void updateItemQuantity(String userId, String productId, int quantity) throws IOException {
        try (Table table = hbaseConnection.getTable(TABLE_NAME)) {
             if (quantity <= 0) {
                removeItem(userId, productId);
                return;
            }
            Put put = new Put(Bytes.toBytes(userId));
            put.addColumn(CF_ITEMS, Bytes.toBytes(productId), Bytes.toBytes(quantity));
            table.put(put);
        }
    }

    public void removeItem(String userId, String productId) throws IOException {
        try (Table table = hbaseConnection.getTable(TABLE_NAME)) {
            Delete delete = new Delete(Bytes.toBytes(userId));
            delete.addColumn(CF_ITEMS, Bytes.toBytes(productId));
            table.delete(delete);
        }
    }
    
    public void clearCart(String userId) throws IOException {
        try (Table table = hbaseConnection.getTable(TABLE_NAME)) {
            Delete delete = new Delete(Bytes.toBytes(userId));
            // Deleting the entire row
            table.delete(delete);
        }
    }
} 